<!DOCTYPE html>
<html>
<head>
    <!-- hexo-inject:begin --><!-- hexo-inject:end --><title>博望</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
    <link href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css">
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    
<link rel="stylesheet" href="/css/prism.css">
 
    
<script src="/js/prism.js"></script>

    
    
<link rel="stylesheet" href="/css/index.css">
 
    
<script src="/js/search.js"></script>



     
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML" async></script>
        <script type="text/x-mathjax-config">
            MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
        </script>
     

     
        <script src="//lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js"> </script>
        
<script src="/js/fancybox.js"></script>

    

    <script type="text/javascript">
        var search_path = "search.xml";
        if (search_path.length == 0) {
            search_path = "search.xml";
        }
        var path = "/" + search_path;
        searchFunc(path, 'local-search-input', 'local-search-result');
    </script>
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/themes/prism.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 6.1.0"><!-- hexo-inject:begin --><!-- hexo-inject:end --></head>

    <style>
        .row2 {
            /* --bs-gutter-x: 2.5rem;
            --bs-gutter-y: 0;
            display: flex;
            flex-wrap: wrap;
            margin-top: calc(var(--bs-gutter-y) * -20);
            margin-right: calc(var(--bs-gutter-x) * -2);
            margin-left: calc(var(--bs-gutter-x) * -2); */
        }

        .row-0 {
            width: 0;
        }
    </style>

    <body id="body">
        <!-- hexo-inject:begin --><!-- hexo-inject:end --><!-- 导航栏 -->
        <nav class="navbar navbar-expand-md navbar-dark mb-4 pt-3 pb-3">
    <div class="container" style="display: flex;flex-direction: row;align-items: flex-end;">
        <div style="display: flex;flex-direction: column;">
            <a class="navbar-brand" style='font: bold 29px "Times New Roman", Georgia, Times, sans-serif;
        color: #555;' href="/ ">
                博望
            </a>
            <span style="padding-bottom:7px;padding-right:20px">
                博望不熄
            </span>
        </div>

        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
            aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarCollapse">
            <ul class="navbar-nav me-auto mb-2 mb-md-0" style="color: #555;">
                
 
 

    <li class="nav-item">
        <a class="nav-link" style="color: #555;" href="/">
            <i class="fa fa-home "> </i> 主页
        </a>
    </li>

    <li class="nav-item">
        <a class="nav-link" style="color: #555;" href="/archives">
            <i class="fa fa-archive" "> </i> 归档
        </a>
    </li>
 

            </ul>

            
                <form class="d-flex">
                    <button class="btn text-muted fa fa-search d-none d-md-block d-lg-block" disabled></button>
                    <input id="local-search-input" class="form-control me-2 pe-4" type="search"
                        placeholder="搜索 " aria-label="Search">
                </form>
                

                    <ul class="navbar-nav">
                        
 

                    </ul>
        </div>
    </div>
</nav>

            <main class="container">
                <div class="row row2 pt-3">
                    <!-- 文章 -->
                    <div id="content" class="col-md-12">
                        <div class="markdown-section">
                            <!-- 搜索结果 -->
                            <div id="local-search-result"></div>
                            <!-- 博客详情 -->
<p class="h1">QuickJS JSString&JSAtom</p>

<div class="pb-3">
    <i class="fa fa-calendar p-1"></i>
    2022/05/05 21:02:38 

    <i class="fa fa-folder-open p-1"> </i> 
    <span class="tag-hover">
        
            <a href="/categories/QuickJS/ " class="link-dark text-decoration-none"> 
                QuickJS 
            </a>
         
    </span>

    <i class="fa fa-tag p-1"> </i>
    <span class="tag-hover">
        
            <a href="/tags/QuickJS/" class="link-dark text-decoration-none"> 
                QuickJS 
            </a>
        
    </span>
</div>

<p><img src="/images/quickjs-jsstring-jsatom.svg" alt=" JSString &amp; JSAtom "></p>
<blockquote>
<p>上图看起来有点糊，实际上是因为内容多，文字小，被缩放了。可以放大看，是清晰的</p>
</blockquote>
<h2 id="JSString定义"><a href="#JSString定义" class="headerlink" title="JSString定义"></a>JSString定义</h2><p>QuickJS中，使用JSString结构体封装了字符串变量。使用JSAtom来完成对字符串的存储和比较。QuickJS支持ASCII和Unicode两种字符串编码格式。<br>先看下，它们的定义</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c">
<span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">JSRefCountHeader</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">int</span> ref_count<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span> JSRefCountHeader<span class="token punctuation">;</span>

<span class="token keyword">struct</span> <span class="token punctuation">&#123;</span>
    JSRefCountHeader header<span class="token punctuation">;</span> <span class="token comment">/* must come first, 32-bit */</span>
    <span class="token class-name">uint32_t</span> len <span class="token operator">:</span> <span class="token number">31</span><span class="token punctuation">;</span>
    <span class="token class-name">uint8_t</span> is_wide_char <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">/* 0 = 8 bits, 1 = 16 bits characters */</span>
    <span class="token comment">/* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3,
       for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3
       XXX: could change encoding to have one more bit in hash */</span>
    <span class="token class-name">uint32_t</span> hash <span class="token operator">:</span> <span class="token number">30</span><span class="token punctuation">;</span>
    <span class="token class-name">uint8_t</span> atom_type <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span> <span class="token comment">/* != 0 if atom, JS_ATOM_TYPE_x */</span>
    <span class="token class-name">uint32_t</span> hash_next<span class="token punctuation">;</span> <span class="token comment">/* atom_index for JS_ATOM_TYPE_SYMBOL 使用拉链法解决hash碰撞问题 */</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
    <span class="token keyword">struct</span> <span class="token class-name">list_head</span> link<span class="token punctuation">;</span> <span class="token comment">/* string list */</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    <span class="token keyword">union</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">uint8_t</span> str8<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">/* 8 bit strings will get an extra null terminator */</span>
        <span class="token class-name">uint16_t</span> str16<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span> u<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>JSString是一个结构体。<br>JSString中，第一个JSRefCountHeader是一个结构体。它用来记录引用次数。作用是用来存储该字符串的引用次数，GC程序据此来决定是否回收该内存。len的长度是31bit，用于记录字符串的长度。is_wide_char用于标识该字符串是ASCII还是Unicode编码。hash长度是30bit，是其装载的字符串的hash值，根据hash的定义，该值具有唯一性，因此可用比较字符串内容是否一致。atom_type长度是2bit，标识该JSString的atom_type。它有JS_ATOM_TYPE_STRING、JS_ATOM_TYPE_GLOBAL_SYMBOL、JS_ATOM_TYPE_SYMBOL和JS_ATOM_TYPE_PRIVATE几种值。hash_next是下一个和当前字符串hash相同的字符串在atom_array数组中的索引，作用是使用拉链法解决hash碰撞问题。再然后是一个联合体。定义了8位和16位的字符串，分别用于存储ASCII和Unicode字符串。</p>
<h3 id="创建JSString"><a href="#创建JSString" class="headerlink" title="创建JSString"></a>创建JSString</h3><p>根据字符串创建JSString。需要注意的是，需要区分字符串是纯ascii还是Unicode编码。</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">char</span> <span class="token operator">*</span>buf <span class="token operator">=</span> <span class="token string">"test string"</span><span class="token punctuation">;</span> 
JSString <span class="token operator">*</span>str<span class="token punctuation">;</span>
<span class="token keyword">int</span> len <span class="token operator">=</span> <span class="token function">strlen</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span><span class="token punctuation">;</span>
str <span class="token operator">=</span> <span class="token function">js_alloc_string</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> len<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//调用js_alloc_string创建的对象atom_type=0,字符串内容是空的，因此下面的代码就是将字符串拷贝到其字符串中去 </span>
<span class="token function">memcpy</span><span class="token punctuation">(</span>str<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">,</span> buf<span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//将字符串拷贝进去</span>
str<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">[</span>len<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'\0'</span><span class="token punctuation">;</span><span class="token comment">//截止字符串</span>

<span class="token keyword">static</span> JSString <span class="token operator">*</span><span class="token function">js_alloc_string</span><span class="token punctuation">(</span>JSContext <span class="token operator">*</span>ctx<span class="token punctuation">,</span> <span class="token keyword">int</span> max_len<span class="token punctuation">,</span> <span class="token keyword">int</span> is_wide_char<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    JSString <span class="token operator">*</span>p<span class="token punctuation">;</span>
    p <span class="token operator">=</span> <span class="token function">js_alloc_string_rt</span><span class="token punctuation">(</span>ctx<span class="token operator">-></span>rt<span class="token punctuation">,</span> max_len<span class="token punctuation">,</span> is_wide_char<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">unlikely</span><span class="token punctuation">(</span><span class="token operator">!</span>p<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token function">JS_ThrowOutOfMemory</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> p<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">/* Note: the string contents are uninitialized */</span>
<span class="token keyword">static</span> JSString <span class="token operator">*</span><span class="token function">js_alloc_string_rt</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> <span class="token keyword">int</span> max_len<span class="token punctuation">,</span> <span class="token keyword">int</span> is_wide_char<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    JSString <span class="token operator">*</span>str<span class="token punctuation">;</span>
    str <span class="token operator">=</span> <span class="token function">js_malloc_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>JSString<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>max_len <span class="token operator">&lt;&lt;</span> is_wide_char<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span> <span class="token operator">-</span> is_wide_char<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">unlikely</span><span class="token punctuation">(</span><span class="token operator">!</span>str<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
    str<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span><span class="token comment">//创建一个引用计数</span>
    str<span class="token operator">-></span>is_wide_char <span class="token operator">=</span> is_wide_char<span class="token punctuation">;</span><span class="token comment">//是否是ascii</span>
    str<span class="token operator">-></span>len <span class="token operator">=</span> max_len<span class="token punctuation">;</span><span class="token comment">//字符串长度</span>
    str<span class="token operator">-></span>atom_type <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><span class="token comment">//默认设置不是JSAtom类型</span>
    str<span class="token operator">-></span>hash <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>          <span class="token comment">/* optional but costless */</span>
    str<span class="token operator">-></span>hash_next <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>     <span class="token comment">/* optional */</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
    <span class="token function">list_add_tail</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>str<span class="token operator">-></span>link<span class="token punctuation">,</span> <span class="token operator">&amp;</span>rt<span class="token operator">-></span>string_list<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    <span class="token keyword">return</span> str<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="释放JSString"><a href="#释放JSString" class="headerlink" title="释放JSString"></a>释放JSString</h3><p>就像《权力的游戏》中红包女巫说的一样：All Men Must Die. 事实上，世间万物皆难逃一死。JSString使用完了之后，也需要被释放掉。</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token comment">/* same as JS_FreeValueRT() but faster */</span>
<span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token keyword">void</span> <span class="token function">js_free_string</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> JSString <span class="token operator">*</span>str<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">--</span>str<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>str<span class="token operator">-></span>atom_type<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token function">JS_FreeAtomStruct</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
            <span class="token function">list_del</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>str<span class="token operator">-></span>link<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
            <span class="token function">js_free_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">JS_FreeAtomStruct</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> JSAtomStruct <span class="token operator">*</span>p<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token number">0</span>   </span><span class="token comment">/* JS_ATOM_NULL is not refcounted: __JS_AtomIsConst() includes 0 */</span></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">unlikely</span><span class="token punctuation">(</span>i <span class="token operator">==</span> JS_ATOM_NULL<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        p<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count <span class="token operator">=</span> INT32_MAX <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    <span class="token class-name">uint32_t</span> i <span class="token operator">=</span> p<span class="token operator">-></span>hash_next<span class="token punctuation">;</span>  <span class="token comment">/* atom_index 其含义是某一字符串在rt->atom_array中的索引 */</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>p<span class="token operator">-></span>atom_type <span class="token operator">!=</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        JSAtomStruct <span class="token operator">*</span>p0<span class="token punctuation">,</span> <span class="token operator">*</span>p1<span class="token punctuation">;</span>
        <span class="token class-name">uint32_t</span> h0<span class="token punctuation">;</span>

        h0 <span class="token operator">=</span> p<span class="token operator">-></span>hash <span class="token operator">&amp;</span> <span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_hash_size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        i <span class="token operator">=</span> rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>h0<span class="token punctuation">]</span><span class="token punctuation">;</span>
        p1 <span class="token operator">=</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>p1 <span class="token operator">==</span> p<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>h0<span class="token punctuation">]</span> <span class="token operator">=</span> p1<span class="token operator">-></span>hash_next<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token function">assert</span><span class="token punctuation">(</span>i <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                p0 <span class="token operator">=</span> p1<span class="token punctuation">;</span>
                i <span class="token operator">=</span> p1<span class="token operator">-></span>hash_next<span class="token punctuation">;</span>
                p1 <span class="token operator">=</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>p1 <span class="token operator">==</span> p<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                    p0<span class="token operator">-></span>hash_next <span class="token operator">=</span> p1<span class="token operator">-></span>hash_next<span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token comment">/* insert in free atom list */</span>
    rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">atom_set_free</span><span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_free_index<span class="token punctuation">)</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_free_index <span class="token operator">=</span> i<span class="token punctuation">;</span>
    <span class="token comment">/* free the string structure */</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
    <span class="token function">list_del</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>p<span class="token operator">-></span>link<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    <span class="token function">js_free_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_count<span class="token operator">--</span><span class="token punctuation">;</span>
    <span class="token function">assert</span><span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_count <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">void</span> <span class="token function">js_free_rt</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> <span class="token keyword">void</span> <span class="token operator">*</span>ptr<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    rt<span class="token operator">-></span>mf<span class="token punctuation">.</span><span class="token function">js_free</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>rt<span class="token operator">-></span>malloc_state<span class="token punctuation">,</span> ptr<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>如果JSString是JSAtom类型的，需要调用 JS_FreeAtomStruct 来释放内存。否则，只需要调用 js_free_rt 即可完成释放。js_free_rt 函数比较简单，只是调用了内存释放函数进行了释放。 JS_FreeAtomStruct 稍微复杂一些，我们稍后在介绍玩JSAtom时，再详解。</p>
<h2 id="JSAtom"><a href="#JSAtom" class="headerlink" title="JSAtom"></a>JSAtom</h2><p>JSAtom直接从定义上看，不甚明白。我们来看下QuickJS官方文档是怎么说明它的。</p>
<blockquote>
<p>Object property names and some strings are stored as Atoms (unique<br>strings) to save memory  and allow fast comparison. Atoms are<br>represented as a 32 bit integer. Half of the atom range is  reserved<br>for immediate integer literals from 0 to 2^31 - 1</p>
</blockquote>
<p>什么意思呢？简单翻译下：对象属性名称和一些字符串使用Atoms（唯一字符串）来进行存储以节省内存和允许快速比对。Atoms呈现为32位整数。Atom的一半保留给立即数文本，范围是从0到2^31-1。也就是说，JSAtom创建的目的是：保存对象属性名称和一些字符串，以便于节省内存和方便对字符串的快速比较大小。<br>JSAtom的定义如下，非常简单，字面上理解就是一个32位的无符号整形数字。虽然它只是一个小小的定义，但是却能让人感觉到大大的懵逼。</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">typedef</span> <span class="token class-name">uint32_t</span> JSAtom<span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>

<p>想要搞明白JSAtom，还需要一些其它的代码来辅助。JSAtom有以下几种类型：</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">enum</span> <span class="token punctuation">&#123;</span>
    JS_ATOM_TYPE_STRING <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span>
    JS_ATOM_TYPE_GLOBAL_SYMBOL<span class="token punctuation">,</span>
    JS_ATOM_TYPE_SYMBOL<span class="token punctuation">,</span>
    JS_ATOM_TYPE_PRIVATE<span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>分别表示字符串、全局symbol，symbol和私有类型。<br>所有的JSAtom类型变量统一存储在JSRuntime中。我们把相关代码摘出来一起研究下。</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">struct</span> <span class="token class-name">JSRuntime</span> <span class="token punctuation">&#123;</span>
    
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    
    <span class="token comment">// 记录atom_hash数组的长度</span>
    <span class="token keyword">int</span> atom_hash_size<span class="token punctuation">;</span> <span class="token comment">/* power of two 2二次方*/</span>
    <span class="token comment">// </span>
    <span class="token keyword">int</span> atom_count<span class="token punctuation">;</span><span class="token comment">//当前已经创建的atom的数量</span>
    <span class="token keyword">int</span> atom_size<span class="token punctuation">;</span><span class="token comment">//atom_array的容量</span>
    <span class="token keyword">int</span> atom_count_resize<span class="token punctuation">;</span> <span class="token comment">/* resize hash table at this count atom_count达到这个值时，将会重新给atom_hash数组分配大小*/</span>
    <span class="token comment">//atom_hash是一维数组，以字符串的hash做索引，存储字符串在atom_array中的索引</span>
    <span class="token class-name">uint32_t</span> <span class="token operator">*</span>atom_hash<span class="token punctuation">;</span>
    <span class="token comment">//atom_array是二维数组，存储JSAtomStruct，也就是JSString。每一个字符串可由 atom_hash中存储的索引进行定位</span>
    JSAtomStruct <span class="token operator">*</span><span class="token operator">*</span>atom_array<span class="token punctuation">;</span><span class="token comment">//存储JSString的数组</span>
    <span class="token keyword">int</span> atom_free_index<span class="token punctuation">;</span> <span class="token comment">/* 0 = none 标识当前可用的atom_hash的index*/</span>
 
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
 
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">JSString</span> JSAtomStruct<span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>JSAtom是为了解决JSString存储时内存占用效率低和比较时复杂的问题而出现的。那么它是怎么存储字符串的呢？我们可以看到，上述字段中atom_array是一个JSAtomStruct数组。从上面的定义我们可以看出来，JSAtomStruct其实就是JSString。因此， QuickJS使用atom_array存储JSString。将JSString放入数组中之后，如果才能在需要的时候找到它呢？我们把字符串放在atom_array中了，每一个字符串都对应一个索引，只要知道索引就知道字符串的位置了。 这个索引是一个32位的无符号整数。看起来是不是有点眼熟？JSAtom也是32位无符号整数。对，没错，JSAtom其实就是这个索引。因此，JSAtom其实就是某一个字符串在rt-&gt;atom_array中的索引。<br>可是JSAtom如何来节省内存的呢？<br>如果不使用JSAtom，直接对“hello,world”这个字符串进行存储的话，需要先感觉字符串创建JSString，然后将JSString存入rt-&gt;atom_array中，同时返回字符串所在的内存地址或者atom_array的索引。这将会消耗 11+(32+31+1+30+2+32)&#x2F;8 &#x3D; 27个字节。然后，后面每次存储”hello,world”这个字符串时，都需要多消耗27个字节。如果相同的字符串被多次创建的话，对内存会是一个比较大的开销。但是，如果使用JSAtom的话，首次存储”hello,world”需要消耗 11+(32+31+1+30+2+32)&#x2F;8 &#x3D; 27个字节。以后每次存储时，都会在字符串池–atom_array中搜索一边，如果搜索到字符串池中有相同的字符串时，我们就不存储了，直接返回它在字符串池中的索引即可。这样做，相同字符串，不论存储多少次，都只相当于在内存中存储了一次。如此便节省了内存。<br>但是JSAtom又是如何实现快速比较的呢？<br>字符串的比对，一般是遍历两个字符串数组，一个字节一个字节的进行比对。比如说我们常用的c语言标准库中的strcmp函数在某些系统上就是如此实现的。如果字符串较长，比较频次较高，会消耗较多的cpu和内存占用。而JSAtom将这些字符串的hash(32位无符号整数)计算出来，并保存起来，这样，比较时，只需要比较字符串的hash就好了，因此能节省时间、内存和CPU消耗。<br>说到这里，我们需要提出一个问题，hash能代表字符串吗？能也不能。为什么呢？因为大概率字符串之间的hash值是不同的，所以说能。但是hash存在碰撞问题：两个不同内容的字符串可能其hash值却相同，所以说不能。你可能说：这不是逗我吗？不逗你，QuickJS解决了这个问题。它采用了一种叫做拉链法的思路解决了哈希碰撞问题。在此，我不展开讲拉链法了，有兴趣的读者可以去看看相关介绍文章。回到JSString的定义中去，有一个字段叫做hash_next，就是用拉链法记录下一个相同hash值的字符串在rt-&gt;atom_array中的索引。</p>
<h3 id="使用JSAtom表示JSString"><a href="#使用JSAtom表示JSString" class="headerlink" title="使用JSAtom表示JSString"></a>使用JSAtom表示JSString</h3><p>我们从代码上来看，如何用JSAtome来表示JSString。</p>
<h3 id="计算JSString的hash"><a href="#计算JSString的hash" class="headerlink" title="计算JSString的hash"></a>计算JSString的hash</h3><p>先看看QuickJS是如何计算字符串的hash的。</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token comment">/* XXX: could use faster version ? */</span>
<span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token class-name">uint32_t</span> <span class="token function">hash_string8</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token class-name">uint8_t</span> <span class="token operator">*</span>str<span class="token punctuation">,</span> <span class="token class-name">size_t</span> len<span class="token punctuation">,</span> <span class="token class-name">uint32_t</span> h<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token class-name">size_t</span> i<span class="token punctuation">;</span>

    <span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
        h <span class="token operator">=</span> h <span class="token operator">*</span> <span class="token number">263</span> <span class="token operator">+</span> str<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> h<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token class-name">uint32_t</span> <span class="token function">hash_string16</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token class-name">uint16_t</span> <span class="token operator">*</span>str<span class="token punctuation">,</span>
                                     <span class="token class-name">size_t</span> len<span class="token punctuation">,</span> <span class="token class-name">uint32_t</span> h<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token class-name">size_t</span> i<span class="token punctuation">;</span>

    <span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
        h <span class="token operator">=</span> h <span class="token operator">*</span> <span class="token number">263</span> <span class="token operator">+</span> str<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> h<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">static</span> <span class="token class-name">uint32_t</span> <span class="token function">hash_string</span><span class="token punctuation">(</span><span class="token keyword">const</span> JSString <span class="token operator">*</span>str<span class="token punctuation">,</span> <span class="token class-name">uint32_t</span> h<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>str<span class="token operator">-></span>is_wide_char<span class="token punctuation">)</span>
        h <span class="token operator">=</span> <span class="token function">hash_string16</span><span class="token punctuation">(</span>str<span class="token operator">-></span>u<span class="token punctuation">.</span>str16<span class="token punctuation">,</span> str<span class="token operator">-></span>len<span class="token punctuation">,</span> h<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">else</span>
        h <span class="token operator">=</span> <span class="token function">hash_string8</span><span class="token punctuation">(</span>str<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">,</span> str<span class="token operator">-></span>len<span class="token punctuation">,</span> h<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> h<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>计算JSString的hash方式是调用hash_string函数。这个函数中判断了JSString的编码方式，如果是Unicode就调用hash_string16，否则调用hash_string8。我们简单分析hash_string8。该函数有三个参数，分别是待hash的字符串的内容和长度以及参数h—其值一般为atom_type中的一种。内部代码很简单，就是将h*263加上某一位的字符得到的值重新赋值个h，然后遍历字符串的字符，将字符串中的所有字符都代入计算。最后得到的数字就是该串字符串的hash。可以看出，相同的字符串，当调用hash_string时传入的h不同，得到的hash是不相同的。</p>
<h3 id="JSAtom的创建"><a href="#JSAtom的创建" class="headerlink" title="JSAtom的创建"></a>JSAtom的创建</h3><p>JSAtom是根据JSString创建的。创建Atom在源码中有多个位置，我们举一个例子来看下创建过程。</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token class-name">uint32_t</span> <span class="token function">atom_get_free</span><span class="token punctuation">(</span><span class="token keyword">const</span> JSAtomStruct <span class="token operator">*</span>p<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token class-name">uintptr_t</span><span class="token punctuation">)</span>p <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">static</span> JSAtom <span class="token function">JS_NewAtomStr</span><span class="token punctuation">(</span>JSContext <span class="token operator">*</span>ctx<span class="token punctuation">,</span> JSString <span class="token operator">*</span>p<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    JSRuntime <span class="token operator">*</span>rt <span class="token operator">=</span> ctx<span class="token operator">-></span>rt<span class="token punctuation">;</span>
    <span class="token class-name">uint32_t</span> n<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_num_string</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>n<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">&lt;=</span> JS_ATOM_MAX_INT<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token function">js_free_string</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token function">__JS_AtomFromUInt32</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token comment">/* XXX: should generate an exception */</span>
    <span class="token keyword">return</span> <span class="token function">__JS_NewAtom</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> p<span class="token punctuation">,</span> JS_ATOM_TYPE_STRING<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">static</span> <span class="token keyword">inline</span> BOOL <span class="token function">__JS_AtomIsConst</span><span class="token punctuation">(</span>JSAtom v<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token function">defined</span><span class="token punctuation">(</span>DUMP_LEAKS<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> DUMP_LEAKS <span class="token operator">></span> <span class="token number">1</span></span></span>
        <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token class-name">int32_t</span><span class="token punctuation">)</span>v <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">else</span></span>
        <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token class-name">int32_t</span><span class="token punctuation">)</span>v <span class="token operator">&lt;</span> JS_ATOM_END<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token punctuation">&#125;</span>

<span class="token comment">/* string case (internal). Return JS_ATOM_NULL if error. 'str' is
   freed. */</span>
<span class="token keyword">static</span> JSAtom <span class="token function">__JS_NewAtom</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> JSString <span class="token operator">*</span>str<span class="token punctuation">,</span> <span class="token keyword">int</span> atom_type<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token class-name">uint32_t</span> h<span class="token punctuation">,</span> h1<span class="token punctuation">,</span> i<span class="token punctuation">;</span>
    JSAtomStruct <span class="token operator">*</span>p<span class="token punctuation">;</span>
    <span class="token keyword">int</span> len<span class="token punctuation">;</span>

<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token number">0</span></span></span>
    <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"__JS_NewAtom: "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token function">JS_DumpString</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    <span class="token comment">//在字符串常量池中获取字符串</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>atom_type <span class="token operator">&lt;</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">/* str is not NULL */</span>
        <span class="token comment">//如果str的类型和需要创建的atom_type相等，直接从字符串池中获取它的索引---atom</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>str<span class="token operator">-></span>atom_type <span class="token operator">==</span> atom_type<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token comment">/* str is the atom, return its index */</span>
            i <span class="token operator">=</span> <span class="token function">js_get_atom_index</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">/* reduce string refcount and increase atom's unless constant */</span>
            <span class="token comment">//如果是内置JSAtom，则减少字符串的引用计数</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">__JS_AtomIsConst</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span>
                str<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count<span class="token operator">--</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> i<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token comment">//如果没有，尝试查找已经注册到atom_array中的atom</span>
        <span class="token comment">/* try and locate an already registered atom */</span>
        len <span class="token operator">=</span> str<span class="token operator">-></span>len<span class="token punctuation">;</span>
        h <span class="token operator">=</span> <span class="token function">hash_string</span><span class="token punctuation">(</span>str<span class="token punctuation">,</span> atom_type<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//计算str的hash</span>
        h <span class="token operator">&amp;=</span> JS_ATOM_HASH_MASK<span class="token punctuation">;</span><span class="token comment">//目的是将高两位清空，因为在JSString中，hash(30bit)和atom_type(2bit)共用一个32位内存</span>
        h1 <span class="token operator">=</span> h <span class="token operator">&amp;</span> <span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_hash_size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//确保得到的hash值小于 rt->atom_hash_size</span>
        i <span class="token operator">=</span> rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>h1<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//从atom_hash中获取索引</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token comment">//根据索引，获取已经保存的JSString</span>
            p <span class="token operator">=</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>p<span class="token operator">-></span>hash <span class="token operator">==</span> h <span class="token operator">&amp;&amp;</span>
                p<span class="token operator">-></span>atom_type <span class="token operator">==</span> atom_type <span class="token operator">&amp;&amp;</span>
                p<span class="token operator">-></span>len <span class="token operator">==</span> len <span class="token operator">&amp;&amp;</span>
                <span class="token function">js_string_memcmp</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> str<span class="token punctuation">,</span> len<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token comment">// 找到了跳转到done</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">__JS_AtomIsConst</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span>
                    p<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count<span class="token operator">++</span><span class="token punctuation">;</span>
                <span class="token keyword">goto</span> done<span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
            i <span class="token operator">=</span> p<span class="token operator">-></span>hash_next<span class="token punctuation">;</span><span class="token comment">//拉链法解决hash碰撞，寻找下一个相同hash的JSString，本质是一个JSString在rt->atom_array中的索引</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
        h1 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">/* avoid warning */</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>atom_type <span class="token operator">==</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            h <span class="token operator">=</span> JS_ATOM_HASH_SYMBOL<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            h <span class="token operator">=</span> JS_ATOM_HASH_PRIVATE<span class="token punctuation">;</span>
            atom_type <span class="token operator">=</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">//执行到这里，说明atom_array中没有找到JSString，因此需要创建Atom（即：将JSString注册到atom_array）</span>
    <span class="token comment">//rt->atom_free_index表明首次创建Atom或者atom_array不够用了，因此，需要重新申请内存</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_free_index <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">/* allow new atom entries */</span>
        <span class="token class-name">uint32_t</span> new_size<span class="token punctuation">,</span> start<span class="token punctuation">;</span>
        JSAtomStruct <span class="token operator">*</span><span class="token operator">*</span>new_array<span class="token punctuation">;</span>

        <span class="token comment">/* alloc new with size progression 3/2:
           4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092
           preallocating space for predefined atoms (at least 195).
         */</span>
         <span class="token comment">//计算新的atom_size大小</span>
        new_size <span class="token operator">=</span> <span class="token function">max_int</span><span class="token punctuation">(</span><span class="token number">211</span><span class="token punctuation">,</span> rt<span class="token operator">-></span>atom_size <span class="token operator">*</span> <span class="token number">3</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>new_size <span class="token operator">></span> JS_ATOM_MAX<span class="token punctuation">)</span>
            <span class="token keyword">goto</span> fail<span class="token punctuation">;</span>
        <span class="token comment">/* XXX: should use realloc2 to use slack space 应该使用realloc2来使用空闲空间*/</span>
        <span class="token comment">//根据大小重新申请内存给atom_array，使用realloc的原因是因为之前可能已经存储了数据</span>
        new_array <span class="token operator">=</span> <span class="token function">js_realloc_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span><span class="token operator">*</span>new_array<span class="token punctuation">)</span> <span class="token operator">*</span> new_size<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>new_array<span class="token punctuation">)</span>
            <span class="token keyword">goto</span> fail<span class="token punctuation">;</span>
        <span class="token comment">/* Note: the atom 0 is not used */</span>
        start <span class="token operator">=</span> rt<span class="token operator">-></span>atom_size<span class="token punctuation">;</span>
        <span class="token comment">//如果没有创建过，则第一个位置固定存储为JS_ATOM_NULL </span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>start <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token comment">/* JS_ATOM_NULL entry */</span>
            p <span class="token operator">=</span> <span class="token function">js_mallocz_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>JSAtomStruct<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>p<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token function">js_free_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> new_array<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">goto</span> fail<span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
            p<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>  <span class="token comment">/* not refcounted */</span>
            p<span class="token operator">-></span>atom_type <span class="token operator">=</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
            <span class="token function">list_add_tail</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>p<span class="token operator">-></span>link<span class="token punctuation">,</span> <span class="token operator">&amp;</span>rt<span class="token operator">-></span>string_list<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
            new_array<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> p<span class="token punctuation">;</span>
            rt<span class="token operator">-></span>atom_count<span class="token operator">++</span><span class="token punctuation">;</span>
            start <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token comment">//保存atom_size</span>
        rt<span class="token operator">-></span>atom_size <span class="token operator">=</span> new_size<span class="token punctuation">;</span>
        <span class="token comment">//申请的new_array赋值给rt->atom_array</span>
        rt<span class="token operator">-></span>atom_array <span class="token operator">=</span> new_array<span class="token punctuation">;</span>
        <span class="token comment">//设置atom_array的空闲索引</span>
        rt<span class="token operator">-></span>atom_free_index <span class="token operator">=</span> start<span class="token punctuation">;</span>
        <span class="token comment">//将其它索引全部置空</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">=</span> start<span class="token punctuation">;</span> i <span class="token operator">&lt;</span> new_size<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token class-name">uint32_t</span> next<span class="token punctuation">;</span>
            <span class="token comment">// 将索引号存入申请的rt->atom_array中</span>
            <span class="token comment">// 注意：加1的目的是错开一位，这样好检测空闲地址的索引</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">==</span> <span class="token punctuation">(</span>new_size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                next <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
            <span class="token keyword">else</span>
                next <span class="token operator">=</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
            <span class="token comment">//每一个空白的entry内容都设置为自己的索引+1</span>
            <span class="token comment">/*
            static inline JSAtomStruct *atom_set_free(uint32_t v)
            &#123;
                return (JSAtomStruct *)(((uintptr_t)v &lt;&lt; 1) | 1);
            &#125;
            */</span>
            rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">atom_set_free</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">//如果JSSting不为空</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>str<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>str<span class="token operator">-></span>atom_type <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token comment">//普通字符串</span>
            p <span class="token operator">=</span> str<span class="token punctuation">;</span><span class="token comment">//直接将JSString赋值给p</span>
            p<span class="token operator">-></span>atom_type <span class="token operator">=</span> atom_type<span class="token punctuation">;</span><span class="token comment">//设置类型</span>
            <span class="token comment">//此处没有释放str的内存，直接就使用了他的地址</span>
        <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
            <span class="token comment">//创建一个新的JSString,拷贝了它的内存，并对str进行了释放</span>
            p <span class="token operator">=</span> <span class="token function">js_malloc_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>JSString<span class="token punctuation">)</span> <span class="token operator">+</span>
                             <span class="token punctuation">(</span>str<span class="token operator">-></span>len <span class="token operator">&lt;&lt;</span> str<span class="token operator">-></span>is_wide_char<span class="token punctuation">)</span> <span class="token operator">+</span>
                             <span class="token number">1</span> <span class="token operator">-</span> str<span class="token operator">-></span>is_wide_char<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">unlikely</span><span class="token punctuation">(</span><span class="token operator">!</span>p<span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">goto</span> fail<span class="token punctuation">;</span>
            p<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
            p<span class="token operator">-></span>is_wide_char <span class="token operator">=</span> str<span class="token operator">-></span>is_wide_char<span class="token punctuation">;</span>
            p<span class="token operator">-></span>len <span class="token operator">=</span> str<span class="token operator">-></span>len<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
            <span class="token function">list_add_tail</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>p<span class="token operator">-></span>link<span class="token punctuation">,</span> <span class="token operator">&amp;</span>rt<span class="token operator">-></span>string_list<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
            <span class="token comment">//内存拷贝</span>
            <span class="token function">memcpy</span><span class="token punctuation">(</span>p<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">,</span> str<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">,</span> <span class="token punctuation">(</span>str<span class="token operator">-></span>len <span class="token operator">&lt;&lt;</span> str<span class="token operator">-></span>is_wide_char<span class="token punctuation">)</span> <span class="token operator">+</span>
                   <span class="token number">1</span> <span class="token operator">-</span> str<span class="token operator">-></span>is_wide_char<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//释放str</span>
            <span class="token function">js_free_string</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">//空字符串</span>
        p <span class="token operator">=</span> <span class="token function">js_malloc_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>JSAtomStruct<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* empty wide string */</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>p<span class="token punctuation">)</span>
            <span class="token keyword">return</span> JS_ATOM_NULL<span class="token punctuation">;</span>
        p<span class="token operator">-></span>header<span class="token punctuation">.</span>ref_count <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
        p<span class="token operator">-></span>is_wide_char <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>    <span class="token comment">/* Hack to represent NULL as a JSString */</span>
        p<span class="token operator">-></span>len <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DUMP_LEAKS</span></span>
        <span class="token function">list_add_tail</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>p<span class="token operator">-></span>link<span class="token punctuation">,</span> <span class="token operator">&amp;</span>rt<span class="token operator">-></span>string_list<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">/* use an already free entry */</span>
    i <span class="token operator">=</span> rt<span class="token operator">-></span>atom_free_index<span class="token punctuation">;</span><span class="token comment">//使用空闲的entry</span>
    
<span class="token comment">/*  
    /* 当不同的数据块连续存储时，从一个数据块结构体指针指向相邻的不同的数据块的结构体的时候，只需要指针值加1，而不是加上当前整个结构体的大小。因为结构体指针的移动单位是当前整个结构体的大小。*/</span>
    <span class="token comment">//获取空闲entry的索引，对应下面的atom_set_free，就相对好理解一些</span>
    <span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token class-name">uint32_t</span> <span class="token function">atom_get_free</span><span class="token punctuation">(</span><span class="token keyword">const</span> JSAtomStruct <span class="token operator">*</span>p<span class="token punctuation">)</span>
    <span class="token punctuation">&#123;</span>
        <span class="token comment">//结构体指针右移，将会产生一个结构体size的偏移。换句话说，右移之后指向了相邻的下一个结构体</span>
        <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token class-name">uintptr_t</span><span class="token punctuation">)</span>p <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token comment">//将值左移一位，再或上1</span>
    <span class="token keyword">static</span> <span class="token keyword">inline</span> JSAtomStruct <span class="token operator">*</span><span class="token function">atom_set_free</span><span class="token punctuation">(</span><span class="token class-name">uint32_t</span> v<span class="token punctuation">)</span>
    <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token punctuation">(</span>JSAtomStruct <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token class-name">uintptr_t</span><span class="token punctuation">)</span>v <span class="token operator">&lt;&lt;</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token operator">*</span><span class="token operator">/</span>
    rt<span class="token operator">-></span>atom_free_index <span class="token operator">=</span> <span class="token function">atom_get_free</span><span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//获取下一个空闲的entry索引</span>
    rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> p<span class="token punctuation">;</span><span class="token comment">//将JSString存储到atom_array中</span>

    p<span class="token operator">-></span>hash <span class="token operator">=</span> h<span class="token punctuation">;</span><span class="token comment">//保存hash</span>
    p<span class="token operator">-></span>hash_next <span class="token operator">=</span> i<span class="token punctuation">;</span>   <span class="token comment">/* 拉链法解决hash碰撞 atom_index 记录它在atom_array中的索引
    在这里，将其自己的索引保存在hash_next是因为，根据前面的查找，没有找到有相同索引的其它字符串，所以hash_next在这里暂时设置为自己。
    */</span>
    p<span class="token operator">-></span>atom_type <span class="token operator">=</span> atom_type<span class="token punctuation">;</span><span class="token comment">//设置类型</span>

    <span class="token comment">//将atom_count增加1，它表示已经创建的atom的数量增加1</span>
    rt<span class="token operator">-></span>atom_count<span class="token operator">++</span><span class="token punctuation">;</span>
    
    <span class="token comment">//如果类型不是JS_ATOM_TYPE_SYMBOL，就将rt->atom_hash中的索引保存到hash_next中。为啥？因为JS中每一个symbol是唯一的，所以，每一个symbol字符串都会存储。</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>atom_type <span class="token operator">!=</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// rt->atom_hash[h1] 获取该JSString在atom_hash</span>
        <span class="token comment">// 根据该JSString的hash 获取atom_hash中存储的某JSString在atom_array的索引</span>
        <span class="token comment">// 程序运行到这里，说明是新添加字符串到字符串池中，因此rt->atom_hash[h1]的值肯定是0</span>
        p<span class="token operator">-></span>hash_next <span class="token operator">=</span> rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>h1<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//拉链法解决hash碰撞</span>
        rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>h1<span class="token punctuation">]</span> <span class="token operator">=</span> i<span class="token punctuation">;</span><span class="token comment">//将该JSString在atom_array中的索引保存到以该JSString的hash为索引的atom_hash数组中。</span>
        <span class="token comment">//如果atom_count不够用了，重新申请大小</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">unlikely</span><span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_count <span class="token operator">>=</span> rt<span class="token operator">-></span>atom_count_resize<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token function">JS_ResizeAtomHash</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> rt<span class="token operator">-></span>atom_hash_size <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token comment">//    JS_DumpAtoms(rt);</span>
    <span class="token keyword">return</span> i<span class="token punctuation">;</span>

 fail<span class="token operator">:</span>
    i <span class="token operator">=</span> JS_ATOM_NULL<span class="token punctuation">;</span>
 done<span class="token operator">:</span>
    <span class="token comment">//释放str</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>str<span class="token punctuation">)</span>
        <span class="token function">js_free_string</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> i<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>


<p><em><strong>__JS_NewAtom</strong></em> 是创建Atom的最终实现函数。创建Atom需要JSRuntime、JSString和atom_type三个参数。首先，判断atom_type的类型，如果是0、JS_ATOM_TYPE_STRING或JS_ATOM_TYPE_GLOBAL_SYMBOL，就使用判断字符串池中是否存在了该字符串。如果是JS_ATOM_TYPE_SYMBOL或者JS_ATOM_TYPE_PRIVATE，就重新构建JSAtom。<br>如果atom_type是0、JS_ATOM_TYPE_STRING或JS_ATOM_TYPE_GLOBAL_SYMBOL，首先判断下JSString的类型是否为JSAtom，如果是，就使用 js_get_atom_index 从 rt-&gt;atom_hash 中获取JSString的JSAtom。如果类型不相等，就尝试从 rt-&gt;atom_array 中找到完全相同的JSString。如果找到了，就直接返回该字符串池中的JSAtom。如果不是，继续走下面的流程。这一步中，我们计算了字符串的hash,保存为h，同时计算了该JSString在rt-&gt;atom_hash中存储其在rt-&gt;atom_array索引的索引。<br>然后，接下来是判断 rt-&gt;atom_free_index 是否等于0。如果等于0，说明 rt-&gt;atom_array 内存不够用了，需要分配或扩展内存。分配多少内存呢？每次重新扩展后的内存是原来内存的3&#x2F;2倍。扩展内存使用的是 js_realloc_rt 方法。然后通过 rt-&gt;atom_size 判断字符串池是否被使用过。如果没有，固定设置 rt-&gt;atom_array 第一个entry是空字符串。再将新申请的内存赋值给rt-&gt;atom_array，并重新何止好atom_size大小和atom_array空闲索引。最后，将 atom_array 未用的entry都设置为 (（index&lt;1）|  1 ) 。<br>处理好内存分配之后，继续JSAtom的创建。首先判断JSString指针是否为0，如果为空，则创建一个空的JSString。如果不是，判断JSString的atom_type是否为0，如果为0，设置它的atom_type为需要创建的atom_type。否则，就拷贝一个新的JSString。<br>获取 rt-&gt;atom_array 中的空白索引 rt-&gt;atom_free_index 。我们的JSString将会放在它的这个位置。此外，我们需要更新 rt-&gt;atom_free_index ，将其指向的位置移向下一个entry。此外，需要设置JSString的hash为我们前面计算后存储在h变量中的值。将它的hash_next设置为自己的索引。它的atom_type同样设置为创建时传入的atom_type。同样，需要记加atom_count，它用来存储当前Runtime中共存在多少个JSAtom。<br>如果atom_type不等于JS_ATOM_TYPE_SYMBOL，我们需要将当前JSString的hash_next设置为 rt-&gt;atom_hash 中以h1的值为索引的值。这是为hash碰撞建立一个链表。同时更新  rt-&gt;atom_hash[h1] 的值为本JSString在 rt-&gt;atom_array 中的索引。最后，判断下是否需要扩展atom_hash的大小。<br>最后，创建完毕之后，将本JSString在 rt-&gt;atom_array 中的索引返回。从这里，我们可以看出JSAtom其实本质是JSString在 rt-&gt;atom_array 中索引。</p>
<h3 id="根据JSString获取JSAtom"><a href="#根据JSString获取JSAtom" class="headerlink" title="根据JSString获取JSAtom"></a>根据JSString获取JSAtom</h3><pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">static</span> JSAtom <span class="token function">js_get_atom_index</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> JSAtomStruct <span class="token operator">*</span>p<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token comment">// 首先保存JSString的hash_next,它存储的是和p具有相同hash的另外一个字符串在rt->atom_arrat中的索引。</span>
    <span class="token class-name">uint32_t</span> i <span class="token operator">=</span> p<span class="token operator">-></span>hash_next<span class="token punctuation">;</span>  <span class="token comment">/* atom_index */</span>
    <span class="token comment">//判断JSString的类型是不是JS_ATOM_TYPE_SYMBOL</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>p<span class="token operator">-></span>atom_type <span class="token operator">!=</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token comment">//如果不是JS_ATOM_TYPE_SYMBOL</span>
        JSAtomStruct <span class="token operator">*</span>p1<span class="token punctuation">;</span><span class="token comment">//临时变量</span>
        <span class="token comment">//下面代码中p->hash &amp; (rt->atom_hash_size - 1) 的作用是保证 p->hash 不会超出rt->atom_has的大小，以免出现野指针。</span>
        <span class="token comment">//这句代码的作用是根据该JSString的hash获取该字符串在rt->atom_array中的索引</span>
        i <span class="token operator">=</span> rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>p<span class="token operator">-></span>hash <span class="token operator">&amp;</span> <span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_hash_size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        p1 <span class="token operator">=</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//根据索引，获取对应的字符串</span>
        <span class="token comment">//下面的遍历代码作用是：因为存在hash碰撞的可能性，不同内容的字符串可能存在同一个hash值，因此，需要遍历链表，找出真正的索引---即atom</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>p1 <span class="token operator">!=</span> p<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token function">assert</span><span class="token punctuation">(</span>i <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            i <span class="token operator">=</span> p1<span class="token operator">-></span>hash_next<span class="token punctuation">;</span><span class="token comment">//寻找相同hash的下一个索引</span>
            p1 <span class="token operator">=</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> i<span class="token punctuation">;</span><span class="token comment">//返回atom在rt->atom_array中的索引</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p> 根据已有JSString找到它的JSAtom。首先是取到它的hash_next。根据上面的创建过程，我们知道，如果一个JSAtom的atom_type等于JS_ATOM_TYPE_SYMBOL，那么，它的JSAtom就等于hash_next。如果不等于，我们需要根据它的hash，计算它在atom_hash中存储自己的atom的索引。计算出他在atom_hash中的索引之后，取出它的atom。此时，并不难完全确认这个atom就是它自己的。因为存在hash碰撞的问题，因此，需要遍历它的hash_next，直到完全确认找到的JSString和自己完全一样，才返回JSAtom。</p>
<h2 id="内置JSAtom"><a href="#内置JSAtom" class="headerlink" title="内置JSAtom"></a>内置JSAtom</h2><p>QuickJS在初始化时，创建了一些内置的JSAtom。这些是JavaScript关键字或者一些常用的字符串。通过宏定义的方式，引入quickjs-atom.h中的一些宏定义，以在预处理中创建js_atom_init字符串。<br>quickjs-atom.h</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token comment">/*
 * QuickJS atom definitions
 * 
 * Copyright (c) 2017-2018 Fabrice Bellard
 * Copyright (c) 2017-2018 Charlie Gordon
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */</span>

<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">DEF</span></span>

<span class="token comment">/* Note: first atoms are considered as keywords in the parser */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span> <span class="token string">"null"</span><span class="token punctuation">)</span> <span class="token comment">/* must be first */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>false<span class="token punctuation">,</span> <span class="token string">"false"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>true<span class="token punctuation">,</span> <span class="token string">"true"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">if</span><span class="token punctuation">,</span> <span class="token string">"if"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">else</span><span class="token punctuation">,</span> <span class="token string">"else"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">return</span><span class="token punctuation">,</span> <span class="token string">"return"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>var<span class="token punctuation">,</span> <span class="token string">"var"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>this<span class="token punctuation">,</span> <span class="token string">"this"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>delete<span class="token punctuation">,</span> <span class="token string">"delete"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">,</span> <span class="token string">"void"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">,</span> <span class="token string">"typeof"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>new<span class="token punctuation">,</span> <span class="token string">"new"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>in<span class="token punctuation">,</span> <span class="token string">"in"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>instanceof<span class="token punctuation">,</span> <span class="token string">"instanceof"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">do</span><span class="token punctuation">,</span> <span class="token string">"do"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">while</span><span class="token punctuation">,</span> <span class="token string">"while"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">for</span><span class="token punctuation">,</span> <span class="token string">"for"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">break</span><span class="token punctuation">,</span> <span class="token string">"break"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">continue</span><span class="token punctuation">,</span> <span class="token string">"continue"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">switch</span><span class="token punctuation">,</span> <span class="token string">"switch"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">case</span><span class="token punctuation">,</span> <span class="token string">"case"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">default</span><span class="token punctuation">,</span> <span class="token string">"default"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>throw<span class="token punctuation">,</span> <span class="token string">"throw"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>try<span class="token punctuation">,</span> <span class="token string">"try"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>catch<span class="token punctuation">,</span> <span class="token string">"catch"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>finally<span class="token punctuation">,</span> <span class="token string">"finally"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>function<span class="token punctuation">,</span> <span class="token string">"function"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>debugger<span class="token punctuation">,</span> <span class="token string">"debugger"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>with<span class="token punctuation">,</span> <span class="token string">"with"</span><span class="token punctuation">)</span>
<span class="token comment">/* FutureReservedWord */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>class<span class="token punctuation">,</span> <span class="token string">"class"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">const</span><span class="token punctuation">,</span> <span class="token string">"const"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">enum</span><span class="token punctuation">,</span> <span class="token string">"enum"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>export<span class="token punctuation">,</span> <span class="token string">"export"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>extends<span class="token punctuation">,</span> <span class="token string">"extends"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>import<span class="token punctuation">,</span> <span class="token string">"import"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>super<span class="token punctuation">,</span> <span class="token string">"super"</span><span class="token punctuation">)</span>
<span class="token comment">/* FutureReservedWords when parsing strict mode code */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>implements<span class="token punctuation">,</span> <span class="token string">"implements"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>interface<span class="token punctuation">,</span> <span class="token string">"interface"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>let<span class="token punctuation">,</span> <span class="token string">"let"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>package<span class="token punctuation">,</span> <span class="token string">"package"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>private<span class="token punctuation">,</span> <span class="token string">"private"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>protected<span class="token punctuation">,</span> <span class="token string">"protected"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>public<span class="token punctuation">,</span> <span class="token string">"public"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span><span class="token keyword">static</span><span class="token punctuation">,</span> <span class="token string">"static"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>yield<span class="token punctuation">,</span> <span class="token string">"yield"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>await<span class="token punctuation">,</span> <span class="token string">"await"</span><span class="token punctuation">)</span>

<span class="token comment">/* empty string */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>empty_string<span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span>
<span class="token comment">/* identifiers */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span> <span class="token string">"length"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> <span class="token string">"fileName"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>lineNumber<span class="token punctuation">,</span> <span class="token string">"lineNumber"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>message<span class="token punctuation">,</span> <span class="token string">"message"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>errors<span class="token punctuation">,</span> <span class="token string">"errors"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>stack<span class="token punctuation">,</span> <span class="token string">"stack"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> <span class="token string">"name"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>toString<span class="token punctuation">,</span> <span class="token string">"toString"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>toLocaleString<span class="token punctuation">,</span> <span class="token string">"toLocaleString"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>valueOf<span class="token punctuation">,</span> <span class="token string">"valueOf"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>eval<span class="token punctuation">,</span> <span class="token string">"eval"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>prototype<span class="token punctuation">,</span> <span class="token string">"prototype"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>constructor<span class="token punctuation">,</span> <span class="token string">"constructor"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>configurable<span class="token punctuation">,</span> <span class="token string">"configurable"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>writable<span class="token punctuation">,</span> <span class="token string">"writable"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>enumerable<span class="token punctuation">,</span> <span class="token string">"enumerable"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> <span class="token string">"value"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>get<span class="token punctuation">,</span> <span class="token string">"get"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>set<span class="token punctuation">,</span> <span class="token string">"set"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>of<span class="token punctuation">,</span> <span class="token string">"of"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>__proto__<span class="token punctuation">,</span> <span class="token string">"__proto__"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>undefined<span class="token punctuation">,</span> <span class="token string">"undefined"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>number<span class="token punctuation">,</span> <span class="token string">"number"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>boolean<span class="token punctuation">,</span> <span class="token string">"boolean"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>string<span class="token punctuation">,</span> <span class="token string">"string"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>object<span class="token punctuation">,</span> <span class="token string">"object"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>symbol<span class="token punctuation">,</span> <span class="token string">"symbol"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>integer<span class="token punctuation">,</span> <span class="token string">"integer"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>unknown<span class="token punctuation">,</span> <span class="token string">"unknown"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>arguments<span class="token punctuation">,</span> <span class="token string">"arguments"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>callee<span class="token punctuation">,</span> <span class="token string">"callee"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>caller<span class="token punctuation">,</span> <span class="token string">"caller"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_eval_<span class="token punctuation">,</span> <span class="token string">"&lt;eval>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_ret_<span class="token punctuation">,</span> <span class="token string">"&lt;ret>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_var_<span class="token punctuation">,</span> <span class="token string">"&lt;var>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_arg_var_<span class="token punctuation">,</span> <span class="token string">"&lt;arg_var>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_with_<span class="token punctuation">,</span> <span class="token string">"&lt;with>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>lastIndex<span class="token punctuation">,</span> <span class="token string">"lastIndex"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span> <span class="token string">"target"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> <span class="token string">"index"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> <span class="token string">"input"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>defineProperties<span class="token punctuation">,</span> <span class="token string">"defineProperties"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>apply<span class="token punctuation">,</span> <span class="token string">"apply"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>join<span class="token punctuation">,</span> <span class="token string">"join"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>concat<span class="token punctuation">,</span> <span class="token string">"concat"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>split<span class="token punctuation">,</span> <span class="token string">"split"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>construct<span class="token punctuation">,</span> <span class="token string">"construct"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>getPrototypeOf<span class="token punctuation">,</span> <span class="token string">"getPrototypeOf"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>setPrototypeOf<span class="token punctuation">,</span> <span class="token string">"setPrototypeOf"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>isExtensible<span class="token punctuation">,</span> <span class="token string">"isExtensible"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>preventExtensions<span class="token punctuation">,</span> <span class="token string">"preventExtensions"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>has<span class="token punctuation">,</span> <span class="token string">"has"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>deleteProperty<span class="token punctuation">,</span> <span class="token string">"deleteProperty"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>defineProperty<span class="token punctuation">,</span> <span class="token string">"defineProperty"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>getOwnPropertyDescriptor<span class="token punctuation">,</span> <span class="token string">"getOwnPropertyDescriptor"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>ownKeys<span class="token punctuation">,</span> <span class="token string">"ownKeys"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>add<span class="token punctuation">,</span> <span class="token string">"add"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>done<span class="token punctuation">,</span> <span class="token string">"done"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>next<span class="token punctuation">,</span> <span class="token string">"next"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>values<span class="token punctuation">,</span> <span class="token string">"values"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span> <span class="token string">"source"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>flags<span class="token punctuation">,</span> <span class="token string">"flags"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>global<span class="token punctuation">,</span> <span class="token string">"global"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>unicode<span class="token punctuation">,</span> <span class="token string">"unicode"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>raw<span class="token punctuation">,</span> <span class="token string">"raw"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>new_target<span class="token punctuation">,</span> <span class="token string">"new.target"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>this_active_func<span class="token punctuation">,</span> <span class="token string">"this.active_func"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>home_object<span class="token punctuation">,</span> <span class="token string">"&lt;home_object>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>computed_field<span class="token punctuation">,</span> <span class="token string">"&lt;computed_field>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>static_computed_field<span class="token punctuation">,</span> <span class="token string">"&lt;static_computed_field>"</span><span class="token punctuation">)</span> <span class="token comment">/* must come after computed_fields */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>class_fields_init<span class="token punctuation">,</span> <span class="token string">"&lt;class_fields_init>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>brand<span class="token punctuation">,</span> <span class="token string">"&lt;brand>"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>hash_constructor<span class="token punctuation">,</span> <span class="token string">"#constructor"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>as<span class="token punctuation">,</span> <span class="token string">"as"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>from<span class="token punctuation">,</span> <span class="token string">"from"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>meta<span class="token punctuation">,</span> <span class="token string">"meta"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_default_<span class="token punctuation">,</span> <span class="token string">"*default*"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>_star_<span class="token punctuation">,</span> <span class="token string">"*"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Module<span class="token punctuation">,</span> <span class="token string">"Module"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>then<span class="token punctuation">,</span> <span class="token string">"then"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>resolve<span class="token punctuation">,</span> <span class="token string">"resolve"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>reject<span class="token punctuation">,</span> <span class="token string">"reject"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>promise<span class="token punctuation">,</span> <span class="token string">"promise"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>proxy<span class="token punctuation">,</span> <span class="token string">"proxy"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>revoke<span class="token punctuation">,</span> <span class="token string">"revoke"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>async<span class="token punctuation">,</span> <span class="token string">"async"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>exec<span class="token punctuation">,</span> <span class="token string">"exec"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>groups<span class="token punctuation">,</span> <span class="token string">"groups"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>status<span class="token punctuation">,</span> <span class="token string">"status"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>reason<span class="token punctuation">,</span> <span class="token string">"reason"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>globalThis<span class="token punctuation">,</span> <span class="token string">"globalThis"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">CONFIG_BIGNUM</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>bigint<span class="token punctuation">,</span> <span class="token string">"bigint"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>bigfloat<span class="token punctuation">,</span> <span class="token string">"bigfloat"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>bigdecimal<span class="token punctuation">,</span> <span class="token string">"bigdecimal"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>roundingMode<span class="token punctuation">,</span> <span class="token string">"roundingMode"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>maximumSignificantDigits<span class="token punctuation">,</span> <span class="token string">"maximumSignificantDigits"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>maximumFractionDigits<span class="token punctuation">,</span> <span class="token string">"maximumFractionDigits"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">CONFIG_ATOMICS</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>not_equal<span class="token punctuation">,</span> <span class="token string">"not-equal"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>timed_out<span class="token punctuation">,</span> <span class="token string">"timed-out"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>ok<span class="token punctuation">,</span> <span class="token string">"ok"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>toJSON<span class="token punctuation">,</span> <span class="token string">"toJSON"</span><span class="token punctuation">)</span>
<span class="token comment">/* class names */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Object<span class="token punctuation">,</span> <span class="token string">"Object"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Array<span class="token punctuation">,</span> <span class="token string">"Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Error<span class="token punctuation">,</span> <span class="token string">"Error"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Number<span class="token punctuation">,</span> <span class="token string">"Number"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>String<span class="token punctuation">,</span> <span class="token string">"String"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Boolean<span class="token punctuation">,</span> <span class="token string">"Boolean"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol<span class="token punctuation">,</span> <span class="token string">"Symbol"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Arguments<span class="token punctuation">,</span> <span class="token string">"Arguments"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Math<span class="token punctuation">,</span> <span class="token string">"Math"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>JSON<span class="token punctuation">,</span> <span class="token string">"JSON"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Date<span class="token punctuation">,</span> <span class="token string">"Date"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Function<span class="token punctuation">,</span> <span class="token string">"Function"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>GeneratorFunction<span class="token punctuation">,</span> <span class="token string">"GeneratorFunction"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>ForInIterator<span class="token punctuation">,</span> <span class="token string">"ForInIterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>RegExp<span class="token punctuation">,</span> <span class="token string">"RegExp"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>ArrayBuffer<span class="token punctuation">,</span> <span class="token string">"ArrayBuffer"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>SharedArrayBuffer<span class="token punctuation">,</span> <span class="token string">"SharedArrayBuffer"</span><span class="token punctuation">)</span>
<span class="token comment">/* must keep same order as class IDs for typed arrays */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Uint8ClampedArray<span class="token punctuation">,</span> <span class="token string">"Uint8ClampedArray"</span><span class="token punctuation">)</span> 
<span class="token function">DEF</span><span class="token punctuation">(</span>Int8Array<span class="token punctuation">,</span> <span class="token string">"Int8Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Uint8Array<span class="token punctuation">,</span> <span class="token string">"Uint8Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Int16Array<span class="token punctuation">,</span> <span class="token string">"Int16Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Uint16Array<span class="token punctuation">,</span> <span class="token string">"Uint16Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Int32Array<span class="token punctuation">,</span> <span class="token string">"Int32Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Uint32Array<span class="token punctuation">,</span> <span class="token string">"Uint32Array"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">CONFIG_BIGNUM</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>BigInt64Array<span class="token punctuation">,</span> <span class="token string">"BigInt64Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>BigUint64Array<span class="token punctuation">,</span> <span class="token string">"BigUint64Array"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Float32Array<span class="token punctuation">,</span> <span class="token string">"Float32Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Float64Array<span class="token punctuation">,</span> <span class="token string">"Float64Array"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>DataView<span class="token punctuation">,</span> <span class="token string">"DataView"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">CONFIG_BIGNUM</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>BigInt<span class="token punctuation">,</span> <span class="token string">"BigInt"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>BigFloat<span class="token punctuation">,</span> <span class="token string">"BigFloat"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>BigFloatEnv<span class="token punctuation">,</span> <span class="token string">"BigFloatEnv"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>BigDecimal<span class="token punctuation">,</span> <span class="token string">"BigDecimal"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>OperatorSet<span class="token punctuation">,</span> <span class="token string">"OperatorSet"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Operators<span class="token punctuation">,</span> <span class="token string">"Operators"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Map<span class="token punctuation">,</span> <span class="token string">"Map"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Set<span class="token punctuation">,</span> <span class="token string">"Set"</span><span class="token punctuation">)</span> <span class="token comment">/* Map + 1 */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>WeakMap<span class="token punctuation">,</span> <span class="token string">"WeakMap"</span><span class="token punctuation">)</span> <span class="token comment">/* Map + 2 */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>WeakSet<span class="token punctuation">,</span> <span class="token string">"WeakSet"</span><span class="token punctuation">)</span> <span class="token comment">/* Map + 3 */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Map_Iterator<span class="token punctuation">,</span> <span class="token string">"Map Iterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Set_Iterator<span class="token punctuation">,</span> <span class="token string">"Set Iterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Array_Iterator<span class="token punctuation">,</span> <span class="token string">"Array Iterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>String_Iterator<span class="token punctuation">,</span> <span class="token string">"String Iterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>RegExp_String_Iterator<span class="token punctuation">,</span> <span class="token string">"RegExp String Iterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Generator<span class="token punctuation">,</span> <span class="token string">"Generator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Proxy<span class="token punctuation">,</span> <span class="token string">"Proxy"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Promise<span class="token punctuation">,</span> <span class="token string">"Promise"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>PromiseResolveFunction<span class="token punctuation">,</span> <span class="token string">"PromiseResolveFunction"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>PromiseRejectFunction<span class="token punctuation">,</span> <span class="token string">"PromiseRejectFunction"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>AsyncFunction<span class="token punctuation">,</span> <span class="token string">"AsyncFunction"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>AsyncFunctionResolve<span class="token punctuation">,</span> <span class="token string">"AsyncFunctionResolve"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>AsyncFunctionReject<span class="token punctuation">,</span> <span class="token string">"AsyncFunctionReject"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>AsyncGeneratorFunction<span class="token punctuation">,</span> <span class="token string">"AsyncGeneratorFunction"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>AsyncGenerator<span class="token punctuation">,</span> <span class="token string">"AsyncGenerator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>EvalError<span class="token punctuation">,</span> <span class="token string">"EvalError"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>RangeError<span class="token punctuation">,</span> <span class="token string">"RangeError"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>ReferenceError<span class="token punctuation">,</span> <span class="token string">"ReferenceError"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>SyntaxError<span class="token punctuation">,</span> <span class="token string">"SyntaxError"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>TypeError<span class="token punctuation">,</span> <span class="token string">"TypeError"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>URIError<span class="token punctuation">,</span> <span class="token string">"URIError"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>InternalError<span class="token punctuation">,</span> <span class="token string">"InternalError"</span><span class="token punctuation">)</span>
<span class="token comment">/* private symbols */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Private_brand<span class="token punctuation">,</span> <span class="token string">"&lt;brand>"</span><span class="token punctuation">)</span>
<span class="token comment">/* symbols */</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_toPrimitive<span class="token punctuation">,</span> <span class="token string">"Symbol.toPrimitive"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_iterator<span class="token punctuation">,</span> <span class="token string">"Symbol.iterator"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_match<span class="token punctuation">,</span> <span class="token string">"Symbol.match"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_matchAll<span class="token punctuation">,</span> <span class="token string">"Symbol.matchAll"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_replace<span class="token punctuation">,</span> <span class="token string">"Symbol.replace"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_search<span class="token punctuation">,</span> <span class="token string">"Symbol.search"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_split<span class="token punctuation">,</span> <span class="token string">"Symbol.split"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_toStringTag<span class="token punctuation">,</span> <span class="token string">"Symbol.toStringTag"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_isConcatSpreadable<span class="token punctuation">,</span> <span class="token string">"Symbol.isConcatSpreadable"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_hasInstance<span class="token punctuation">,</span> <span class="token string">"Symbol.hasInstance"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_species<span class="token punctuation">,</span> <span class="token string">"Symbol.species"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_unscopables<span class="token punctuation">,</span> <span class="token string">"Symbol.unscopables"</span><span class="token punctuation">)</span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_asyncIterator<span class="token punctuation">,</span> <span class="token string">"Symbol.asyncIterator"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">CONFIG_BIGNUM</span></span>
<span class="token function">DEF</span><span class="token punctuation">(</span>Symbol_operatorSet<span class="token punctuation">,</span> <span class="token string">"Symbol.operatorSet"</span><span class="token punctuation">)</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
    
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span> <span class="token comment">/* DEF */</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>再来看看如何创建内部JSAtom</p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token keyword">enum</span> <span class="token punctuation">&#123;</span>
    __JS_ATOM_NULL <span class="token operator">=</span> JS_ATOM_NULL<span class="token punctuation">,</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name function">DEF</span><span class="token expression"><span class="token punctuation">(</span>name<span class="token punctuation">,</span> str<span class="token punctuation">)</span> JS_ATOM_ </span><span class="token punctuation">##</span> <span class="token expression">name<span class="token punctuation">,</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"quickjs-atom.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">undef</span> <span class="token expression">DEF</span></span>
    JS_ATOM_END<span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">static</span> <span class="token keyword">const</span> <span class="token keyword">char</span> js_atom_init<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name function">DEF</span><span class="token expression"><span class="token punctuation">(</span>name<span class="token punctuation">,</span> str<span class="token punctuation">)</span> str </span><span class="token string">"\0"</span>  <span class="token comment">//使用'\0'截断字符串</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"quickjs-atom.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">undef</span> <span class="token expression">DEF</span></span>
<span class="token punctuation">;</span>

<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

<span class="token comment">//更改AtomHash的大小</span>
<span class="token comment">//两个参数，一个是JSRuntime，atom是存储在里面的。</span>
<span class="token comment">//第二个参数是新的hash数组大小</span>
<span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">JS_ResizeAtomHash</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> <span class="token keyword">int</span> new_hash_size<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    JSAtomStruct <span class="token operator">*</span>p<span class="token punctuation">;</span><span class="token comment">//JSAtomStruct即为JSString</span>
    <span class="token class-name">uint32_t</span> new_hash_mask<span class="token punctuation">,</span> h<span class="token punctuation">,</span> i<span class="token punctuation">,</span> hash_next1<span class="token punctuation">,</span> j<span class="token punctuation">,</span> <span class="token operator">*</span>new_hash<span class="token punctuation">;</span>
    
    <span class="token comment">// rt->atom_hash 里面装的是字符串在rt->atom_array的索引</span>
    <span class="token comment">//字符串在rt->atom_array里面是如何存储的？</span>
    <span class="token comment">//根据rt->atom_free_index获取空白的index，将字符串保存在该位置</span>
    
    <span class="token comment">//p->hash 存储的是字符串的hash</span>
    <span class="token comment">//p->hash_next 存储的是rt->atom_array中p的index</span>
    
    <span class="token comment">//rt->atom_hash 存储的是以字符串的hash为索引的字符串在rt->atom_array中的索引 </span>
    <span class="token comment">//rt->atom_array 是JSString类型数组，存储的是JSString</span>
    <span class="token comment">//rt->atom_free_index 保存的是rt->atom_array空白索引位置</span>
    
    <span class="token comment">// power of 2 ? 2的次方</span>
    <span class="token function">assert</span><span class="token punctuation">(</span><span class="token punctuation">(</span>new_hash_size <span class="token operator">&amp;</span> <span class="token punctuation">(</span>new_hash_size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* power of two */</span>
    <span class="token comment">//size减1</span>
    new_hash_mask <span class="token operator">=</span> new_hash_size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span><span class="token comment">//什么作用？首先看上一行的断言，目的是判断new_hash_size是不是2的次方，如：2，4，8，16都是2的次方数。但是6，10，12，14就不是2的次方数。如果不是，直接报错了，后面就不运行了。 从二进制上看，一个2的次方的数减一之后，其实就相当于将该2进制数最高位设置为零，然后后面的所有位设置为1。以8为例子，二进制表示是 0b00001000。减一之后是7，用二进制表示是0b00000111。 得到这个数字的作用是：一个数与这个数进行与运算时，将会把这个数的最高位全部设置为0。也就是说，一个数字和new_hash_mask做与操作，得到的数字不会大于new_hash_size，用来限制新生成的数字的大小。</span>
    
    <span class="token comment">// 给new_hash分配内存，大小是 sizeof(rt->atom_hash[0]) * new_hash_size</span>
    <span class="token comment">// rt->atom_hash 的定义是 uint32_t *atom_hash</span>
    <span class="token comment">// 那么显然sizeof(rt->atom_hash[0])等于4byte</span>
    new_hash <span class="token operator">=</span> <span class="token function">js_mallocz_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">*</span> new_hash_size<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//new_hash内的值都是0</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>new_hash<span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token comment">//进行内存拷贝同时更新字符串之间的hash链    </span>
    <span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> rt<span class="token operator">-></span>atom_hash_size<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">//遍历原来的atom_hash数组，根据其存储的索引，建立新atom_hash中的索引</span>
        <span class="token comment">//h是什么含义？JSRuntime中的atom_hash数组存放字符串hash值到atom_array的映射</span>
        h <span class="token operator">=</span> rt<span class="token operator">-></span>atom_hash<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//获取对应i位置的hash值</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>h <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token comment">//根据hash获取对应位置的JSAtomStruct其实就是JSString</span>
            <span class="token comment">//疑问：这个hash会不会溢出数组？不会，可以看下面的新hash计算的代码。</span>
            <span class="token comment">// p->hash &amp; new_hash_mask 保证了生成的新hash不会大于new_hash_size</span>
            p <span class="token operator">=</span> rt<span class="token operator">-></span>atom_array<span class="token punctuation">[</span>h<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//获取对应位置的JSAtomStruct其实就是JSString</span>
            hash_next1 <span class="token operator">=</span> p<span class="token operator">-></span>hash_next<span class="token punctuation">;</span><span class="token comment">//暂存下一个hash值，用于下一个遍历</span>
            <span class="token comment">/* add in new hash table */</span>
            <span class="token comment">//根据取出来的JSString的hash得到新的atom_array的index</span>
            j <span class="token operator">=</span> p<span class="token operator">-></span>hash <span class="token operator">&amp;</span> new_hash_mask<span class="token punctuation">;</span><span class="token comment">//根据上面的解释，新的计算新的atom_array中的hash_index，&amp;new_hash_mask操作保证了新的hash不会溢出数组</span>
            <span class="token comment">//new_hash[j]里面的值可能为0，也可能不为0。</span>
            <span class="token comment">//这里，根据新的规则，先将new_hash[j]赋值到hash_next中</span>
            p<span class="token operator">-></span>hash_next <span class="token operator">=</span> new_hash<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//将JSAtomStruct的hash_next赋值为new_hash[j]</span>
            new_hash<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> h<span class="token punctuation">;</span><span class="token comment">//将原来的字符串在atom_array的索引保存到新的atom_array的新位置中</span>
            h <span class="token operator">=</span> hash_next1<span class="token punctuation">;</span><span class="token comment">//根据其原来的hash_next将原来hash相同的字符串全部重新映射一边</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">js_free_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> rt<span class="token operator">-></span>atom_hash<span class="token punctuation">)</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_hash <span class="token operator">=</span> new_hash<span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_hash_size <span class="token operator">=</span> new_hash_size<span class="token punctuation">;</span><span class="token comment">//</span>
    <span class="token comment">/* return the max count from the hash size */</span>
    <span class="token comment">//#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2) </span>
    rt<span class="token operator">-></span>atom_count_resize <span class="token operator">=</span> <span class="token function">JS_ATOM_COUNT_RESIZE</span><span class="token punctuation">(</span>new_hash_size<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//    JS_DumpAtoms(rt);</span>
    <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>


<span class="token comment">/* only works with zero terminated 8 bit strings */</span>
<span class="token keyword">static</span> JSAtom <span class="token function">__JS_NewAtomInit</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">char</span> <span class="token operator">*</span>str<span class="token punctuation">,</span> <span class="token keyword">int</span> len<span class="token punctuation">,</span>
                               <span class="token keyword">int</span> atom_type<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    JSString <span class="token operator">*</span>p<span class="token punctuation">;</span>
    p <span class="token operator">=</span> <span class="token function">js_alloc_string_rt</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> len<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>p<span class="token punctuation">)</span>
        <span class="token keyword">return</span> JS_ATOM_NULL<span class="token punctuation">;</span>
    <span class="token function">memcpy</span><span class="token punctuation">(</span>p<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">,</span> str<span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span>
    p<span class="token operator">-></span>u<span class="token punctuation">.</span>str8<span class="token punctuation">[</span>len<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'\0'</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">__JS_NewAtom</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> p<span class="token punctuation">,</span> atom_type<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">JS_InitAtoms</span><span class="token punctuation">(</span>JSRuntime <span class="token operator">*</span>rt<span class="token punctuation">)</span>
<span class="token punctuation">&#123;</span>
    <span class="token keyword">int</span> i<span class="token punctuation">,</span> len<span class="token punctuation">,</span> atom_type<span class="token punctuation">;</span>
    <span class="token keyword">const</span> <span class="token keyword">char</span> <span class="token operator">*</span>p<span class="token punctuation">;</span>

    rt<span class="token operator">-></span>atom_hash_size <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_hash <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_size <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    rt<span class="token operator">-></span>atom_free_index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">JS_ResizeAtomHash</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> <span class="token number">256</span><span class="token punctuation">)</span><span class="token punctuation">)</span>     <span class="token comment">/* there are at least 195 predefined atoms */</span>
        <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>

    p <span class="token operator">=</span> js_atom_init<span class="token punctuation">;</span>
    <span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> JS_ATOM_END<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">==</span> JS_ATOM_Private_brand<span class="token punctuation">)</span>
            atom_type <span class="token operator">=</span> JS_ATOM_TYPE_PRIVATE<span class="token punctuation">;</span>
        <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">>=</span> JS_ATOM_Symbol_toPrimitive<span class="token punctuation">)</span>
            atom_type <span class="token operator">=</span> JS_ATOM_TYPE_SYMBOL<span class="token punctuation">;</span>
        <span class="token keyword">else</span>
            atom_type <span class="token operator">=</span> JS_ATOM_TYPE_STRING<span class="token punctuation">;</span>
        len <span class="token operator">=</span> <span class="token function">strlen</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//计算当前字符串长度</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">__JS_NewAtomInit</span><span class="token punctuation">(</span>rt<span class="token punctuation">,</span> p<span class="token punctuation">,</span> len<span class="token punctuation">,</span> atom_type<span class="token punctuation">)</span> <span class="token operator">==</span> JS_ATOM_NULL<span class="token punctuation">)</span>
            <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
        p <span class="token operator">=</span> p <span class="token operator">+</span> len <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span><span class="token comment">//指针移向下一个字符串</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>其中JS_ATOM_END作为内置JSAtom结束的标记索引。QuickJS在创建JSRuntime时，会初始化这些内置JSAtom。首先需要清空JSAtom相关字段。然后，为atom_hash分配内存，在这里，我们分配它的初始大小为256。通过分析 JS_ResizeAtomHash 方法的代码，我们可以知道它的平衡因子为2。JS_ResizeAtomHash 对 rt-&gt;atom_hash 进行扩展的原理就是根据需要的分配内存大小，申请新的内存块。然后将之前存储的数据，拷贝到新申请的内存中。这中间，因为有hash碰撞的问题，需要更新 rt-&gt;atom_array中每一个JSString的hash_next。最后就是遍历js_atom_init，生成这些基础的JSAtom。生成JSAtom调用的是 __JS_NewAtomInit 方法，这个方法，我们前面剖析过，在此不赘述。</p>
<h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>至此，我们完整分析了JSString和JSAtom。通过使用JSAtom，有效的节省了内存消耗和提高了字符串比较效率。</p>
 

<div class="p-2 pe-4">
     
        <a href="/2022/05/12/QuickJS%E6%95%B0%E5%AD%97%E5%AD%97%E9%9D%A2%E9%87%8F/" class="btn btn-outline-secondary btn-sm float-start">
            <small>
                < 上一篇：QuickJS数字字面量
            </small>
        </a>
     
     
        <a href="/2022/05/05/QuickJS%E5%AD%97%E8%8A%82%E7%A0%81%E6%89%93%E5%8D%B0/" class="btn btn-outline-secondary btn-sm float-end" >
            <small>
                下一篇：QuickJS字节码打印 >
            </small>
        </a>
     
</div>
                        </div>
                    </div>

                    <!-- sidebar -->
                    <div id="slidebar">
                        <div class="border-auto ps-2 pe-1 pb-2 pt-2">
    
        <!-- 侧边栏 分类 -->
<div class="card mb-3">
    <h6 class="card-header tag-hover"><i class="fa fa-folder-open pe-2"></i>分类
        
    </h6>
    <div class="card-body">
        <ul class="list-group border-0">
            
            
             
            <a class="list-group-item border-0 pt-0 pb-0 ps-1" href="/categories/QuickJS/ ">
                QuickJS <span class="badge bg-secondary float-end m-1">3</span>
            </a>
              
        </ul>

        <ul class="list-group border-0 collapse" id="category">
            
        </ul>
    </div>
</div>

 
    
        <!-- 侧边栏 标签 -->
<div class="card mb-3">
    <h6 class="card-header tag-hover"><i class="fa fa-tag pe-2"></i>标签
        
    </h6>

    <div class="card-body tag-hover">
        
        
             
            <a class="text-decoration-none border-0 d-inline-flex link-dark pt-0 pb-0 p-0" href="/tags/QuickJS/ ">
                QuickJS <span class="badge bg-secondary float-end m-1">6</span>
            </a>
          

        <span id="tags" class="collapse">
            
        </span>
    </div>
</div>
 
    
        <div class="card mb-3">
    <h6 class="card-header"><i class="fa fa-clock-o pe-2"></i>最近文章</h6>
    <div class="card-body tag-hover">
        <ul class="list-group border-0">
            
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6" style="margin-bottom: 10px;" href="/2022/05/05/QuickJS-JSString-JSAtom/ ">
                    <small> QuickJS JSString&JSAtom </small>
                </a>
            
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6" style="margin-bottom: 10px;" href="/2022/05/05/QuickJS%E5%AD%97%E8%8A%82%E7%A0%81%E6%89%93%E5%8D%B0/ ">
                    <small> QuickJS字节码打印 </small>
                </a>
            
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6" style="margin-bottom: 10px;" href="/2022/05/05/QuickJS%E6%93%8D%E4%BD%9C%E7%A0%81/ ">
                    <small> QuickJS操作码 </small>
                </a>
            
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6" style="margin-bottom: 10px;" href="/2022/05/12/QuickJS%E6%95%B0%E5%AD%97%E5%AD%97%E9%9D%A2%E9%87%8F/ ">
                    <small> QuickJS数字字面量 </small>
                </a>
            
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6" style="margin-bottom: 10px;" href="/2022/05/16/QuickJS-JavaScript%E4%B8%96%E7%95%8C%E7%9A%84%E5%8E%9F%E5%A7%8B%E5%8E%9F%E5%9E%8B%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BB%BA%E7%AB%8B/ ">
                    <small> QuickJS JavaScript世界的原始原型对象的建立 </small>
                </a>
            
             
        </ul>
    </div>
</div> 
    
        <div class="card mb-3">
    <h6 class="card-header"><i class="fa fa-link pe-2"></i>友情链接</h6>
    <div class="card-body tag-hover">
        <ul class="list-group border-0">
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6 text" target="_blank" rel="noopener" href="https://blog.csdn.net/jayyuz ">
                    <small>CSDN</small>
                </a>
            
                <a class="list-group-item border-0 pt-0 pb-0 ps-1 fs-6 text" target="_blank" rel="noopener" href="https://smartlink.xin ">
                    <small>Smartlink</small>
                </a>
             
        </ul>
    </div>
</div> 
    
</div>
                    </div>
                </div>
            </main>


            <!-- footer -->
            <footer id="footer" class="bg-dark pt-3 pb-0 mt-5">
    <div class="container pb-4 pt-4 text-center">
        <p class="text-muted tag-hover"> Copyright © 2022 <a class="link-secondary text-decoration-none" target="_blank" rel="noopener" href="https://hexo.io"> SmartLink </a><br> <a class="link-secondary text-decoration-none" target="_blank" rel="noopener" href="https://github.com/smile-yan/hexo-theme-heyan"> Hexo </a> Theme <a class="link-secondary text-decoration-none" target="_blank" rel="noopener" href="https://github.com/smile-yan/hexo-theme-heyan"> heyan </a> 
            <br>
            <a class="link-secondary text-decoration-none" target="_blank" rel="noopener" href="https://beian.miit.gov.cn/#/Integrated/index">
                 
            </a>
        </p>
    </div>
</footer>
    <!-- hexo injector body_end start -->
<script src="/assets/prism-bundle.js"></script>
<script src="/assets/prism-plus.js" data-pjax=""></script>
<!-- hexo injector body_end end --><!-- hexo-inject:begin --><!-- hexo-inject:end --></body>
    <script>
        // 获取屏幕高度 document.documentElement.clientHeight
        console.log(document.documentElement.clientHeight);
        // 获取屏幕宽度 document.documentElement.clientWidth
        console.log(document.documentElement.clientWidth);
        if (document.documentElement.clientHeight > document.documentElement.clientWidth) {
            console.log('remove slidebar')
            document.getElementById("slidebar").remove()
            document.getElementById("content").className = "col-md-12";//单个class  
        } else {
            document.getElementById("slidebar").className = "col-md-2";//单个class  
            document.getElementById("content").className = "col-md-10";//单个class  
        }
    </script>
    <!-- https://cdn.jsdelivr.net/npm/vanta@0.5.22/dist/vanta.birds.min.js -->
    <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vanta@0.5.22/dist/vanta.dots.min.js"></script>
    <script>
        VANTA.DOTS({
            el: "#footer",
            mouseControls: true,
            touchControls: true,
            gyroControls: false,
            minHeight: 200.00,
            minWidth: 200.00,
            scale: 1.00,
            scaleMobile: 1.00,
            size: 2.20,
            spacing: 13.00
        })
    </script> -->

    <!-- <script src="https://cdn.jsdelivr.net/npm/vanta@0.5.22/dist/vanta.clouds2.min.js"></script>
    <script>
        VANTA.CLOUDS2({
            el: "#footer",
            mouseControls: true,
            touchControls: true,
            gyroControls: false,
            minHeight: 200.00,
            minWidth: 200.00,
            scale: 1.00,
            speed: 2.10,
            texturePath: "https://www.vantajs.com/gallery/noise.png"
        })
    </script> -->

</html>